package com.oceanstar.service.Impl;

import com.oceanstar.Pojo.*;
import com.oceanstar.utils.JwtUtils;
import com.oceanstar.mapper.UserInfoMapper;
import com.oceanstar.service.IUserInfoService;
import io.jsonwebtoken.Claims;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.Period;
import java.time.format.DateTimeFormatter;
import java.text.SimpleDateFormat;
import java.util.*;

@Service
public class UserInfoServiceImpl implements IUserInfoService {
    // 注入mapper
    private final UserInfoMapper userInfoMapper;
    // 构造器注入
    public UserInfoServiceImpl(UserInfoMapper userInfoMapper) {
        this.userInfoMapper = userInfoMapper;
    }

    @Override
    public void insert(UserInfo userInfo) throws Exception {
        // 1. 检查手机号是否已存在
        if (userInfoMapper.selectByPhone(userInfo.getPhone()) != null) {
            throw new Exception("手机号已存在");
        }

        // 2. 验证身份证号
        String idCard = userInfo.getIdCard();
        if (idCard == null || idCard.trim().isEmpty()) {
            throw new Exception("身份证号不能为空");
        }

        // 长度验证
        int length = idCard.length();
        if (length != 15 && length != 18) {
            throw new Exception("身份证号必须是15位或18位");
        }

        // 生日日期验证
        String birthdayStr;
        if (length == 18) {
            birthdayStr = idCard.substring(6, 14); // 提取yyyyMMdd
        } else {
            birthdayStr = "19" + idCard.substring(6, 12); // 15位转成yyyyMMdd
        }

        try {
            // 解析日期
            java.time.format.DateTimeFormatter formatter = java.time.format.DateTimeFormatter.ofPattern("yyyyMMdd");
            java.time.LocalDate birthday = java.time.LocalDate.parse(birthdayStr, formatter);

            // 验证年份不早于1900
            if (birthday.getYear() < 1900) {
                throw new Exception("身份证生日年份不能早于1900年");
            }

            // 验证不晚于当前日期
            if (birthday.isAfter(java.time.LocalDate.now())) {
                throw new Exception("身份证生日不能晚于当前日期");
            }

        } catch (java.time.format.DateTimeParseException e) {
            throw new Exception("身份证生日日期格式不正确");
        }

        // 设置创建时间 - 使用MySQL兼容的datetime格式
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date now = new Date();
        userInfo.setCreateTime(dateFormat.format(now));
        userInfo.setUpdateTime(dateFormat.format(now));

        userInfoMapper.insertUser(userInfo);
    }

    /*
     * 登录
     */
    @Override
    public LoginInfo login(UserInfo user) {
        //1. 调用mapper接口, 根据用户名和密码查询员工信息
        UserInfo e = userInfoMapper.selectByUsernameAndPassword(user);
        //2. 判断: 判断是否存在, 如果存在, 组装登录成功信息
        if(e != null){
            //生成JWT令牌
            System.out.println(e);
            Map<String, Object> claims = new HashMap<>();
            claims.put("id",e.getId());
            claims.put("identity", e.getIdentity());
            claims.put("name", e.getName());
            String jwt = JwtUtils.generateToken(claims);


            //并且更新最后登陆时间
             userInfoMapper.updateLastLoginTime(e.getId());


             return new LoginInfo(e.getId(),e.getName(),e.getIdentity() ,jwt);
        }
        //3. 不存在, 返回null
        return null;
    }

    @Override
    public PageInfo<UserInfo> getUserList(UserQueryDTO queryDTO, HttpServletRequest request) throws Exception {
        // 处理name参数的URL解码
        String name = request.getParameter("name");
        if (name != null) {
            try {
                // 如果name包含URL编码，进行解码
                name = java.net.URLDecoder.decode(name, "UTF-8");
                queryDTO.setName(name);
            } catch (Exception e) {
                // 解码失败时使用原始值
                queryDTO.setName(name);
            }
        }
        
        // 参数校验
        if (queryDTO.getPage() == null || queryDTO.getPage() < 1) {
            queryDTO.setPage(1);
        }
        if (queryDTO.getPageSize() == null || queryDTO.getPageSize() < 1) {
            queryDTO.setPageSize(10);
        }

        // 计算分页偏移量
        Integer offset = (queryDTO.getPage() - 1) * queryDTO.getPageSize();

        // 构建查询条件
        UserInfo userInfo = new UserInfo();
        BeanUtils.copyProperties(queryDTO, userInfo);

        // 查询当前页数据
        List<UserInfo> userList = userInfoMapper.selectUserList(userInfo, offset, queryDTO.getPageSize());

        // 查询总记录数
        long total = userInfoMapper.countUserList(userInfo);

        // 构建并返回PageResult对象
        return new PageInfo<>(total, userList);
    }

    @Override
    @Transactional
    public void deleteUsers(Number[] ids) {
        try {
            userInfoMapper.deleteUsers(ids);
        } catch (Exception e) {
            throw new RuntimeException("删除用户失败", e);
        }
    }

    @Override
    public void updateUsers(UserInfo userInfo, String token) throws Exception {
        // 检查该用户是否存在
        Claims parsedClaims = JwtUtils.parseToken(token);
        Integer id = (Integer) parsedClaims.get("id");
        if (userInfoMapper.selectById(id) == null) {
            throw new Exception("该用户不存在");
        }
        // 更新时间
        userInfo.setUpdateTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        // 更新用户信息
        userInfo.setId(id);
        userInfoMapper.updateUsers(userInfo);
    }

    @Override
    public void updateUsersByAdmin(UserInfo userInfo, String token) {
        // 检查该用户是否存在
        Claims parsedClaims = JwtUtils.parseToken(token);
        // 检查管理员权限
        if ((Integer) parsedClaims.get("identity") != 3) {
            throw new RuntimeException("权限不足");
        }
        // 更新时间
        userInfo.setUpdateTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        // 更新用户信息
        userInfoMapper.updateUsersByAdmin(userInfo);
    }

    @Override
    public List<UserInfo> getAllUsers(String token) throws Exception {
        // 解析token
        Claims parsedClaims = JwtUtils.parseToken(token);
        // 检查管理员权限
        if ((Integer) parsedClaims.get("identity") != 3) {
            throw new Exception("权限不足");
        }
        return userInfoMapper.getAllUsers();
    }

    @Override
    public UserInfo getUserInfo(String token){
        Claims parsedClaims = JwtUtils.parseToken(token);
        Integer id = (Integer) parsedClaims.get("id");
        return userInfoMapper.selectById(id);
    }

    /*
     *家属绑定老人
     */
    @Override
    public void bindFamily(BindFamily bindFamily, String token) throws Exception {
        //检查该老人账户是非存在
        if(userInfoMapper.selectByPhone(bindFamily.getPhone()) == null) {
            throw new Exception("不存在该老人信息");
        }
        Claims claims = JwtUtils.parseToken(token);
        Integer id = (Integer) claims.get("id");
        UserInfo userInfo = userInfoMapper.selectByPhone(bindFamily.getPhone());
        if(!Objects.equals(userInfo.getIdCard(), bindFamily.getIdCard())) {
            throw new Exception("身份证号码错误");
        }
        userInfo.setEmergencyId(id);
        userInfoMapper.updateUsers(userInfo);
        UserInfo userInfo1 = userInfoMapper.selectById(id);
        userInfo1.setRelation(bindFamily.getRelation());
        userInfo1.setBindId(userInfoMapper.selectByPhone(bindFamily.getPhone()).getId());
        String formattedDate = LocalDate.now().format(DateTimeFormatter.ISO_DATE);
        userInfo1.setBindTime(formattedDate);
        userInfoMapper.updateBindFamilyById(id,userInfo1);
    }

    /*
     *查询该家属绑定的老人
     */
    @Override
    public SelectElderDTO selectElder(String token) throws Exception {
        //检查家属是否绑定老人
        Claims claims = JwtUtils.parseToken(token);
        Integer id = (Integer) claims.get("id");
        UserInfo userInfo = userInfoMapper.selectById(id);
        if(userInfo.getBindId() == null) {
            throw new Exception("未绑定老人！");
        }
        SelectElderDTO elderDTO = new SelectElderDTO();
        UserInfo userInfo1 = userInfoMapper.selectById(userInfo.getBindId());
        elderDTO.setElderId(userInfo1.getId());
        elderDTO.setName(userInfo1.getName());
        elderDTO.setRelation(userInfo.getRelation());

        //计算老人年龄
        String birthDateStr = userInfo1.getIdCard().substring(6, 14);
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
        LocalDate birthDate = LocalDate.parse(birthDateStr, formatter);
        LocalDate currentDate = LocalDate.now();
        elderDTO.setAge(Period.between(birthDate, currentDate).getYears());

        if(userInfo1.getGender() == 1)
            elderDTO.setGender("男");
        else
            elderDTO.setGender("女");
        elderDTO.setBindDate(userInfo.getBindTime());
        return elderDTO;
    }

    /*
     *查询老人绑定的家属信息
     */
    @Override
    public List<SelectFamilyDTO> selectFamily(Integer elderId) throws Exception {
        // 检查老人是否存在
        UserInfo elder = userInfoMapper.selectById(elderId);
        if (elder == null) {
            throw new Exception("老人信息不存在");
        }
        
        // 查询绑定到该老人的所有家属
        List<UserInfo> families = userInfoMapper.selectFamiliesByElderId(elderId);
        
        if (families.isEmpty()) {
            throw new Exception("该老人未绑定任何家属");
        }
        
        // 构建返回对象列表
        List<SelectFamilyDTO> familyDTOList = new ArrayList<>();
        for (UserInfo family : families) {
            SelectFamilyDTO familyDTO = new SelectFamilyDTO();
            familyDTO.setFamilyId(family.getId());
            familyDTO.setName(family.getName());
            familyDTO.setGender(family.getGender());
            familyDTO.setRelation(family.getRelation());
            familyDTO.setPhone(family.getPhone());
            familyDTO.setAddress(family.getAddress());
            familyDTO.setBindDate(family.getBindTime());
            familyDTOList.add(familyDTO);
        }
        
        return familyDTOList;
    }

    /*
     *管理员将一个或多个老人分配给指定的网格员，实现绑定关系。
     */
    @Override
    public AssignedElderDTO assignElderToGrid(Integer gridId, List<Integer> elderlyIds, String token) throws Exception {
        // 1. 验证管理员权限
        Claims claims = JwtUtils.parseToken(token);
        Integer identity = (Integer) claims.get("identity");
        if (identity != 3) {
            throw new Exception("需为管理员权限");
        }

        // 2. 验证网格员是否存在
        UserInfo info = userInfoMapper.selectById(gridId);
        if (info == null || info.getIdentity() !=4) {
            throw new Exception("网格员不存在");
        }

        // 3. 预先验证所有老人是否存在
        List<Integer> notExistIds = new ArrayList<>();
        Map<Integer, UserInfo> elderMap = new HashMap<>();

        for (Integer elderId : elderlyIds) {
            UserInfo elder = userInfoMapper.selectById(elderId);
            if (elder == null || elder.getIdentity() != 1) {
                notExistIds.add(elderId);
            } else {
                elderMap.put(elderId, elder);
            }
        }

        // 如果有不存在的老人ID，直接返回错误
        if (!notExistIds.isEmpty()) {
            throw new Exception("以下ID非老人或不存在: " + notExistIds);
        }

        // 4. 验证是否已被分配给其他网格员
        for (UserInfo elder : elderMap.values()) {
            if (elder.getGridId() != null && !elder.getGridId().equals(gridId)) {
                throw new Exception("老人 " + elder.getName() + " 已被分配给其他网格员，请先解除原绑定关系");
            }
        }

        // 5. 执行分配（所有验证通过后才开始更新）
        List<AssignedElder> assignedElders = new ArrayList<>();
        for (UserInfo elder : elderMap.values()) {
            // 如果已经分配给当前网格员，跳过更新
            if (!gridId.equals(elder.getGridId())) {
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                String currentDate = sdf.format(new Date());

                userInfoMapper.assignElderToGrid(elder.getId(), gridId, currentDate);
            }

            AssignedElder assignedElder = new AssignedElder();
            assignedElder.setElderlyId(elder.getId());
            assignedElder.setName(elder.getName());
            assignedElders.add(assignedElder);
        }

        // 6. 设置返回结果
        AssignedElderDTO dto = new AssignedElderDTO();
        dto.setGridId(gridId);
        dto.setAssignedCount(assignedElders.size());
        dto.setAssignedElders(assignedElders);

        return dto;
    }

    /*
     *管理员将一个或多个老人与网格员解绑。
     */
    @Override
    public UnassignedElderDTO unassignElderToGrid(Integer gridId, List<Integer> elderlyIds, String token) throws Exception {
        // 1. 验证管理员权限
        Claims claims = JwtUtils.parseToken(token);
        Integer identity = (Integer) claims.get("identity");
        if (identity != 3) {
            throw new Exception("需为管理员权限");
        }

        // 2. 验证网格员是否存在
        UserInfo info = userInfoMapper.selectById(gridId);
        if (info == null || info.getIdentity() !=4) {
            throw new Exception("网格员不存在");
        }

        // 3. 预先验证所有老人是否存在
        List<Integer> notExistIds = new ArrayList<>();
        Map<Integer, UserInfo> elderMap = new HashMap<>();

        for (Integer elderId : elderlyIds) {
            UserInfo elder = userInfoMapper.selectById(elderId);
            if (elder == null || elder.getIdentity() != 1) {
                notExistIds.add(elderId);
            } else {
                elderMap.put(elderId, elder);
            }
        }

        // 如果有不存在的老人ID，直接返回错误
        if (!notExistIds.isEmpty()) {
            throw new Exception("以下ID非老人或不存在: " + notExistIds);
        }

        // 5. 执行解绑（所有验证通过后才开始更新）
        List<AssignedElder> assignedElders = new ArrayList<>();
        for (UserInfo elder : elderMap.values()) {
            // 如果老人未绑定该网格员，自动忽略
            if (!gridId.equals(elder.getGridId())) {
                continue;
            }

            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            String currentDate = sdf.format(new Date());
            userInfoMapper.unassignElder(elder.getId(), currentDate);
            AssignedElder assignedElder = new AssignedElder();
            assignedElder.setElderlyId(elder.getId());
            assignedElder.setName(elder.getName());
            assignedElders.add(assignedElder);
        }

        // 6. 设置返回结果
        UnassignedElderDTO dto = new UnassignedElderDTO();
        dto.setGridId(gridId);
        dto.setUnassignedCount(assignedElders.size());
        dto.setUnassignedElders(assignedElders);

        return dto;
    }

    /*
     *管理员查看指定网格员当前已绑定的老人列表，可分页、可筛选。
     */
    @Override
    public GridBindingsResponse getGridBindings(Integer gridId, Integer page, Integer pageSize, String name, String token) throws Exception {
        // 1. 验证管理员权限
        Claims claims = JwtUtils.parseToken(token);
        Integer identity = (Integer) claims.get("identity");
        if (identity != 3) {
            throw new Exception("需为管理员权限");
        }

        // 2. 验证网格员是否存在
        UserInfo info = userInfoMapper.selectById(gridId);
        if (info == null || info.getIdentity() !=4) {
            throw new Exception("网格员不存在");
        }

        // 3. 构建返回
        int offset = (page - 1) * pageSize;

        Long total = userInfoMapper.countGridBindings(gridId, name);

        List<ElderBindingInfo> rows = userInfoMapper.selectGridBindings(gridId, offset, pageSize, name);

        UserInfo grid = userInfoMapper.selectById(gridId);
        GridBindingsResponse response = new GridBindingsResponse();
        response.setGridId(gridId);
        response.setGridName(grid.getName());
        response.setTotal(total);
        response.setRows(rows);

        return response;
    }
}
